﻿Imports System.Text

Public Class clsMakeSpanWithRes
    Const INT_SIZE As Int32 = 4

    Public Enum eDirection
        Left
        Right
    End Enum
    Public Function CalcMakeSpan(ByRef actList As HashSet(Of Int32),
                                 ByRef projInfo As clsProject,
                                 ByRef diagrams As Dictionary(Of String, Int32()()),
                                 ByRef res_hash As Dictionary(Of Int32, Int32()),
                                 Optional ByVal justify As eDirection = eDirection.Left,
                                 Optional ByVal bDocument As Boolean = False) As Int32
        Try
            Dim makespan As Int32
            Dim scheduleInfos As New clsScheduleInfos(projInfo)
            scheduleInfos.Init(projInfo, diagrams)
            For Each act As Int32 In actList
                Dim task As clsTask = projInfo.TasksA(act)
                Dim faz As Int32 = task.FAZ
                ' faz recalc
                For Each pre As Int32 In task.Pre
                    If pre > 0 Then
                        Dim pTask As clsTask = projInfo.TasksA(pre)
                        Dim comp As Int32 = pTask.PlanedAt + pTask.Duration
                        faz = Math.Max(faz, comp)
                    End If
                Next
                'task planed after max pre Finish Time
                Dim duration As Int32 = task.Duration
                Dim resource() As Int32 = res_hash(act)
                Dim zeile(scheduleInfos.count) As Int32
                Dim shifter As Int32 = 0
                'If bDocument Then
                '    'old alg, not correct, slower!
                '    ' ResourcePlaceable(odiagram, zeile, faz, shifter, resource, duration, task.Key, justify, maxres, projInfo)
                'End If
                shifter = ResourceContraintCalc(projInfo, justify, resource, faz, duration, task.Key, scheduleInfos.maxres, scheduleInfos.actMaxResource, scheduleInfos.actPeakResource, Nothing, scheduleInfos.odiagram)
                Dim bRecalc As Boolean = False
                makespan = Math.Max(makespan, faz + shifter + duration)
            Next
            projInfo.PeakResource = scheduleInfos.actPeakResource
            projInfo.Diagramm = scheduleInfos.odiagram
            Return makespan
        Catch ex As Exception
            Throw
        End Try
    End Function
    Private Sub RemovePosts(ByVal task As clsTask, ByRef projInfo As clsProject, ByRef ht As Dictionary(Of Int32, clsTask))
        Try
            Dim tr As clsTask = task
            For Each post As Int32 In tr.Post
                If projInfo.Tasks.ContainsKey(post) Then
                    Dim p As clsTask = projInfo.Tasks(post)
                    If Not ht.ContainsKey(post) Then
                        ht.Add(p.Key, p.Clone(True))
                        p.Reset()
                        RemovePosts(p, projInfo, ht)
                    End If
                    'pre-restriction
                End If
            Next

        Catch ex As Exception
            Throw
        End Try
    End Sub

    Private Function ArrayCopy(ByVal source()() As Int32, ByVal rowsize As Int32, ByVal colsize As Int32, ByVal rowPos As Int32, ByVal colPos As Int32) As Int32()()
        Try
            If rowsize = 0 Or colsize = 0 Then
                Return Nothing
            End If
            Dim x(rowsize - 1)() As Int32
            Dim y As Int32 = 0
            Dim lowerbound As Int32 = rowPos
            For rownr As Int32 = lowerbound To lowerbound + rowsize - 1
                Dim size As Int32 = colsize - 1
                Dim col(size) As Int32
                Buffer.BlockCopy(source(rownr), colPos * INT_SIZE, col, 0, colsize * INT_SIZE)
                x(y) = col
                y += 1
            Next
            Return x
        Catch ex As Exception
            Throw
        End Try
    End Function
    Public Function ResourceContraintCalc(ByRef projInfo As clsProject, ByVal justify As eDirection, ByVal resource() As Int32,
                                           ByVal faz As Int32, ByVal dur As Int32, ByVal tasknr As Int32, ByVal maxres() As Int32,
                                           ByRef actMaxResource()() As Int32, ByRef actPeakResource()() As Int32,
                                           ByRef taskList() As HashSet(Of Int32), ByRef oDiagramm()()() As Int32,
                                       Optional ByVal bDoc As Boolean = False) As Int32
        Try
            Dim startTime As Int32 = 0
            Dim endTime As Int32 = 0
            Dim a As Int32 = tasknr
            Dim shifter As Int32 = 0
            Dim einplanen As Boolean = False
            Dim anzRes As Int32 = resource.Length - 1
            Dim k As Int32
            Do Until einplanen
                startTime = faz + shifter
                endTime = startTime + dur - 1
                einplanen = True
                For k = 0 To anzRes ' resources
                    Dim iMaxRes As Int32 = maxres(k)
                    Dim iRes As Int32 = resource(k)
                    If iRes > 0 Then 'do not check tasks with res=0 
                        Dim t As Int32
                        For t = startTime To endTime
                            If iMaxRes - actPeakResource(k)(t) < iRes Then
                                'shift if resource full
                                einplanen = False
                                shifter += 1
                                Exit For
                            End If
                        Next
                        If einplanen = False Then
                            Exit For
                        End If
                    End If
                Next
            Loop
            'planning
            For k = 0 To anzRes
                Dim iRes As Int32 = resource(k)
                If iRes > 0 Then 'zero resource check
                    'task-resource position 
                    Dim t As Int32
                    For t = startTime To endTime
                        'extended documentation => CPU cost!
                        If document Then
                            For d As Int32 = actPeakResource(k)(t) To actPeakResource(k)(t) + resource(k) - 1
                                oDiagramm(k)(d)(t) = tasknr
                            Next
                        End If
                        actPeakResource(k)(t) += iRes
                    Next
                End If
            Next
            projInfo.TasksA(tasknr).PlanedAt = startTime
            Return shifter
        Catch ex As Exception
            Throw
        End Try
    End Function
End Class
